/**
 * @file    pc_jbd.c
 * @brief   上位机通信协议-JBD协议
 * @author  liuwei 
 * @version 1.0.1
 * @date    2023-06-19
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2023-06-19 <td>1.0.1     <td>Liuwei   <td>首次创建
 * <tr><td>2023-01-03 <td>1.0.2     <td>Liuwei   <td>添加BarCode码
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "pc_jbd.h"
#include "cfg_prj.h"
#include "var_mng.h"
#include "param_mng.h"
#include "diagnosis.h"
#include "pcs_can_mng.h"
#include "pcs_rs485_mng.h"
#include <string.h>
#include "If_com.h"
#include "If_can.h"
#include "sample.h"
#include "soh_calc.h"
#include "soc_calc.h"
/* macro/define --------------------------------------------------------------*/
#define FRAME_HARD    (0xDD)
#define FRAME_END     (0x77)
#define READ_CMD      (0xA5)
#define WRITE_CMD     (0x5A)
#define BROAD_ADDR    (0xFF)
/* typedef -------------------------------------------------------------------*/
typedef struct 
{
    uint8_t hand;
    uint8_t dev_addr;
    uint8_t wr_cmd;
    uint8_t reg_cmd;
    uint8_t len;
    uint8_t data_buf[50];
    uint16_t crc;
    uint8_t end;
}pc_jbd_data_type;

typedef struct 
{
	uint8_t cmd;
	uint8_t(*p_call_func)(pc_jbd_data_type , uint8_t* , uint16_t*);
}jbd_cmd_type;

/* local functions -----------------------------------------------------------*/
static uint16_t pc_jb_calc_crc(uint8_t *rx_buf , uint16_t rx_len);
static uint8_t jbd_read_cmd_00_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);
static uint8_t jbd_read_cmd_03_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //读取基本信息
static uint8_t jbd_read_cmd_04_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //读取单体电压
static uint8_t jbd_read_cmd_05_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //硬件版本号
static uint8_t jbd_read_cmd_AA_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //保护统计次数
static uint8_t jbd_read_cmd_0A_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //控制命令
static uint8_t jbd_read_cmd_0B_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);
static uint8_t jbd_read_cmd_0C_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);
static uint8_t jbd_write_cmd_0A_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //00
static uint8_t jbd_write_cmd_0B_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //00
static uint8_t jbd_write_cmd_0C_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //00
static uint8_t jbd_read_cmd_0F_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //非蓝牙
static uint8_t jbd_write_cmd_E1_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //MOS控制
static uint8_t jbd_read_cmd_param_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //读取参数容量
static uint8_t jbd_write_cmd_param_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //设置容量
static uint8_t jbd_write_cmd_unlock_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num); //参数锁
static uint8_t jbd_write_cmd_lock_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num);  //未做

static uint16_t jbd_get_prp_state(void);
static uint16_t jbd_get_alm_state(void);
static uint16_t jbd_get_pcs_rs485_ptl(void);
static uint16_t jbd_get_pcs_can_ptl(void);
static void jbd_set_pcs_rs485_ptl(uint16_t set_dat);
static void jbd_set_pcs_can_ptl(uint16_t set_dat);
/* static variables ----------------------------------------------------------*/
static jbd_cmd_type read_cmd_list_map[] = 
{
	{0x00 , jbd_read_cmd_00_deal } ,
    {0x03 , jbd_read_cmd_03_deal } ,
    {0x04 , jbd_read_cmd_04_deal } ,
	{0x05 , jbd_read_cmd_05_deal } ,
    {0xAA , jbd_read_cmd_AA_deal } ,
	{0x0A , jbd_read_cmd_0A_deal } ,
	{0x0B , jbd_read_cmd_0B_deal } ,
	{0x0C , jbd_read_cmd_0C_deal } ,
	{0x0F , jbd_read_cmd_0F_deal } ,
};

#define CMD_READ_MAP_SIZE  (sizeof(read_cmd_list_map)/sizeof(jbd_cmd_type))
	
static jbd_cmd_type write_cmd_list_map[] = 
{
	{0x00 , jbd_write_cmd_unlock_deal },
	{0x01 , jbd_write_cmd_lock_deal },
	{0x0A , jbd_write_cmd_0A_deal } ,
	{0x0B , jbd_write_cmd_0B_deal } ,
	{0x0C , jbd_write_cmd_0C_deal } ,
	{0xE1 , jbd_write_cmd_E1_deal } ,
};


#define CMD_WRITE_MAP_SIZE  (sizeof(write_cmd_list_map)/sizeof(jbd_cmd_type))
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
 uint8_t pc_jbd_com_analysis(uint8_t *rx_buf , uint16_t rx_len ,uint8_t *tx_buf , uint16_t *tx_len)
{
    uint16_t calc_crc = 0;
    uint16_t i = 0;
    uint8_t res = FALSE;
    pc_jbd_data_type recv_data = {0};
    if(rx_len < 5)
        return FALSE;
    
    if((rx_buf[0] == FRAME_HARD) && (rx_buf[rx_len - 1] == FRAME_END))
    {
        recv_data.crc = (rx_buf[rx_len - 3] << 8) + rx_buf[rx_len - 2];
		if((READ_CMD == rx_buf[1]) || (WRITE_CMD == rx_buf[1]))
			calc_crc = pc_jb_calc_crc(&rx_buf[2], rx_len - 5); //带地址
		else
			calc_crc = pc_jb_calc_crc(&rx_buf[1], rx_len - 4);  //wifi

		
        if(recv_data.crc == calc_crc)
        {
		if((READ_CMD == rx_buf[1]) || (WRITE_CMD == rx_buf[1]))
		{
			//recv_data.dev_addr = rx_buf[1];
			recv_data.dev_addr = BROAD_ADDR;
			recv_data.wr_cmd = rx_buf[1];
			recv_data.reg_cmd = rx_buf[2];
			recv_data.len = rx_buf[3];
			for( i = 0;(i < rx_buf[3])&&(i < 50) ; ++ i)
			{
				recv_data.data_buf[i] = rx_buf[i + 4];
			}
		}
		else
		{
			recv_data.dev_addr = rx_buf[1];
			recv_data.wr_cmd = rx_buf[2];
			recv_data.reg_cmd = rx_buf[3];
			recv_data.len = rx_buf[4];
			for( i = 0;(i < rx_buf[4])&&(i < 50) ; ++ i)
			{
				recv_data.data_buf[i] = rx_buf[i + 5];
			}
		}			
			if(READ_CMD == recv_data.wr_cmd)
			{
				for( i = 0;i < CMD_READ_MAP_SIZE; ++ i)
				{
					if(read_cmd_list_map[i].cmd == recv_data.reg_cmd)
					{
						res = read_cmd_list_map[i].p_call_func(recv_data , tx_buf , tx_len);
						break;
					}
				}
				
				if(CMD_READ_MAP_SIZE == i)
				{
					res = jbd_read_cmd_param_deal(recv_data , tx_buf , tx_len);
				}
			}
			else if(WRITE_CMD == recv_data.wr_cmd)
			{
				for( i = 0;i < CMD_WRITE_MAP_SIZE; ++ i)
				{
					if(write_cmd_list_map[i].cmd == recv_data.reg_cmd)
					{
						res = write_cmd_list_map[i].p_call_func(recv_data , tx_buf , tx_len);
						break;
					}
				}
				
				if(CMD_WRITE_MAP_SIZE == i)
				{
					res = jbd_write_cmd_param_deal(recv_data , tx_buf , tx_len);
				}
			}
			else
			{
				;
			}
        }
    }

    return res;
}
/** ------------------------------------------------------------------------- *
  *                             Local function
 ** ------------------------------------------------------------------------- */
static uint16_t pc_jb_calc_crc(uint8_t *rx_buf , uint16_t rx_len)
{
    uint16_t calc_len = 0;
    uint16_t i = 0;

    for( i = 0;i < rx_len; ++ i)
    {
        calc_len += rx_buf[i];
    }

    return (~calc_len + 1);
}

static uint8_t jbd_read_cmd_00_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
   
	tx_buf[tx_idx ++ ] = recv_data.wr_cmd;
	tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;
	
    if(recv_data.dev_addr != BROAD_ADDR)
	{
		tx_buf[4] = tx_idx - 5;
		calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
	}
	else
	{
		tx_buf[3] = tx_idx - 4;
		calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);
	}
	
	calc_crc = pc_jb_calc_crc(&tx_buf[3] , tx_idx - 3);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_03_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)  //OK
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t i = 0;
    uint16_t calc_crc = 0;
	uint8_t temp_num = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
	tx_buf[tx_idx ++ ] = 0x00;
	tx_buf[tx_idx ++ ] = 0x00;

    data_temp = var_get_data(VAR_ID_BATT_VOLT);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = var_get_data(VAR_ID_BUS_CURR) - 30000;
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = var_get_data(VAR_ID_DISP_RCAP);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = param_get_data(PAR_ID_FULL_CAP);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = param_get_data(PAR_ID_CYCLE);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = ((param_get_data(PAR_ID_BMS_YEAR) - 2000) << 9) & 0xFE00;
    data_temp += (param_get_data(PAR_ID_BMS_MONTH) << 5) & 0x01E0;
    data_temp += param_get_data(PAR_ID_BMS_DAY) & 0x1F;
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
    
    data_temp = var_get_data(VAR_ID_BLC_NOW_IDX) & 0x1F;
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = 0;
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    data_temp = jbd_get_prp_state();
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;

    tx_buf[tx_idx ++ ] = SOFT_VER_RELEASE * 10;
    tx_buf[tx_idx ++ ] = var_get_data(VAR_ID_DISP_SOC) * 0.01;
    tx_buf[tx_idx ++ ] = var_get_data(VAR_ID_MOS_STATE);
    tx_buf[tx_idx ++ ] = param_get_data(PAR_ID_CB_CELL_NUM);

	temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;

	if(recv_data.dev_addr != BROAD_ADDR)
	{
		data_temp = jbd_get_alm_state();
		tx_buf[tx_idx ++ ] = data_temp >> 8;
		tx_buf[tx_idx ++ ] = data_temp & 0xff;
	
		data_temp = var_get_data(VAR_ID_ENV_TEMP) + 2231;
		tx_buf[tx_idx ++ ] = data_temp >> 8;
		tx_buf[tx_idx ++ ] = data_temp & 0xff;

		data_temp = var_get_data(VAR_ID_MOS_TEMP) + 2231;
		tx_buf[tx_idx ++ ] = data_temp >> 8;
		tx_buf[tx_idx ++ ] = data_temp & 0xff;
		tx_buf[tx_idx ++ ] = temp_num;
	}
	else
    {
		tx_buf[tx_idx ++ ] = temp_num + 2;
		data_temp = var_get_data(VAR_ID_MOS_TEMP) + 2231;
		tx_buf[tx_idx ++ ] = data_temp >> 8;
		tx_buf[tx_idx ++ ] = data_temp & 0xff;

		data_temp = var_get_data(VAR_ID_ENV_TEMP) + 2231;
		tx_buf[tx_idx ++ ] = data_temp >> 8;
		tx_buf[tx_idx ++ ] = data_temp & 0xff;
	}
	
    for( i = 0;i < temp_num ; ++ i)
    {
        data_temp = var_get_data(VAR_ID_CELL_TEMP01 + i) + 2231;
        tx_buf[tx_idx ++ ] = data_temp >> 8;
        tx_buf[tx_idx ++ ] = data_temp & 0xff;
    }
	
	if(recv_data.dev_addr != BROAD_ADDR)
	{
		tx_buf[4] = tx_idx - 5;
		calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
	}
	else
	{
		tx_buf[3] = tx_idx - 4;
		calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);
	}

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_read_cmd_04_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t i = 0;
    uint16_t calc_crc = 0;
	uint8_t cell_num = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;
	
	cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
	if(cell_num >= CELL_MAX_NUM)
		cell_num = CELL_MAX_NUM; 
	
    for( i = 0;i < cell_num; ++ i)
    {
        data_temp = var_get_data(VAR_ID_CELL_VOLT01 + i);
        tx_buf[tx_idx ++ ] = data_temp >> 8;
        tx_buf[tx_idx ++ ] = data_temp & 0xff;
    }
    
    if(recv_data.dev_addr != BROAD_ADDR)
	{
		tx_buf[4] = tx_idx - 5;
		calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
	}
	else
	{
		tx_buf[3] = tx_idx - 4;
		calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);
	}

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_05_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t tx_idx = 0;
    uint16_t i = 0;
    uint16_t calc_crc = 0;
	uint8_t len = 0;
	uint16_t v16_data = 0;
	
	char str[30] = HARD_PLATFORM;
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
	
	v16_data = param_get_data(PAR_ID_MFT_CODE);
	if((v16_data != 0x2020) && (v16_data != 0))
	{
		for(i = 0;i < 15; ++ i)
		{
			v16_data = param_get_data(PAR_ID_MFT_CODE + i);
			str[i * 2] = v16_data;
			str[i * 2 + 1] = v16_data >> 8;
		}
	}
	else
	{
		for(i = 0;i < 15; ++ i)
		{
			v16_data = param_get_data(PAR_ID_SN_CODE + i);
			str[i * 2] = v16_data;
			str[i * 2 + 1] = v16_data >> 8;
		}
	}

	len = strlen(str);
    tx_buf[tx_idx ++ ] = len;
	for(i = 0;i < len; ++ i)
	{
		tx_buf[tx_idx ++] = str[i];
	}
	
    if(recv_data.dev_addr != BROAD_ADDR)
	{
		calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
	}
	else
	{
		calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);
	}

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_AA_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x18;
	
	data_temp = param_get_data(PAR_ID_SC_PRP_TIMES);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_OCC_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_OCD_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_COV_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_CUV_PRP_TIMES);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_OTC_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_UTC_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_OTD_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_UTD_PRP_TIMES);
    tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_BOV_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_BUV_PRP_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
	data_temp = param_get_data(PAR_ID_RESTART_TIMES);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
    tx_buf[tx_idx ++ ] = data_temp & 0xff;
    
    if(recv_data.dev_addr != BROAD_ADDR)
	{
		tx_buf[4] = tx_idx - 5;
		calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
	}
	else
	{
		tx_buf[3] = tx_idx - 4;
		calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);
	}

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_0A_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x02;
	
	data_temp = jbd_get_pcs_rs485_ptl();
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
   
    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_0B_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x02;
	
	data_temp = jbd_get_pcs_can_ptl();
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
   
    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_read_cmd_0C_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t data_temp = 0;
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;

    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x08;
	
	data_temp = var_get_data(VAR_ID_TP_SOP_CV);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
   
	data_temp = var_get_data(VAR_ID_TP_SOP_CC) * 0.1;
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
	
	data_temp = var_get_data(VAR_ID_TP_SOP_DV);
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
	
	data_temp = var_get_data(VAR_ID_TP_SOP_DC) * 0.1;
	tx_buf[tx_idx ++ ] = data_temp >> 8;
	tx_buf[tx_idx ++ ] = data_temp & 0xff;
	
    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	
	*tx_num = tx_idx;
	
    return TRUE;
}

static uint8_t jbd_write_cmd_0A_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	uint16_t set_data = 0;
	
	set_data = (recv_data.data_buf[0] << 8) + recv_data.data_buf[1];
	jbd_set_pcs_rs485_ptl(set_data);
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;

    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_write_cmd_0B_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	uint16_t set_data = 0;
	
	set_data = (recv_data.data_buf[0] << 8) + recv_data.data_buf[1];
	jbd_set_pcs_can_ptl(set_data);
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;

    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_write_cmd_0C_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
    uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
    tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;

    calc_crc = pc_jb_calc_crc(tx_buf , tx_idx);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_read_cmd_0F_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	uint16_t data_val = 0;
	uint8_t i = 0;
	static uint16_t heat_cnt = 0;
	uint8_t cell_num = 0;
	uint8_t temp_num = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
    tx_buf[tx_idx ++ ] = 0x0F;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00; //长度
    tx_buf[tx_idx ++ ] = 0x00; // 状态
	
	data_val = var_get_data(VAR_ID_BATT_VOLT);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = var_get_data(VAR_ID_BUS_CURR) * VAR_CURR_FACTOR - VAR_CURR_OFFSET;
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	tx_buf[tx_idx ++ ] = var_get_data(VAR_ID_DISP_SOC) * 0.01;

	data_val = var_get_data(VAR_ID_DISP_RCAP);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = param_get_data(PAR_ID_FULL_CAP);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = param_get_data(VAR_ID_DISP_RCAP);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = jbd_get_prp_state();
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = var_get_data(VAR_ID_MAX_CELL_VOLT);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = var_get_data(VAR_ID_MIN_CELL_VOLT);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = var_get_data(VAR_ID_BLC_NOW_IDX);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = 0;
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = param_get_data(PAR_ID_CYCLE);
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
    tx_buf[tx_idx ++ ] = var_get_data(VAR_ID_MOS_STATE);
	
	temp_num = param_get_data(PAR_ID_CB_TEMP_NUM);	
	if(temp_num >= CFG_TEMP_NUM)
		temp_num = CFG_TEMP_NUM;
	
	tx_buf[tx_idx ++ ] = temp_num;
	for(i = 0;i < temp_num; ++ i)
	{
		data_val = var_get_data(VAR_ID_CELL_TEMP01 + i) + 2231;
		tx_buf[tx_idx ++ ] = data_val >> 8;
		tx_buf[tx_idx ++ ] = data_val & 0xff;
	}
	
	cell_num = param_get_data(PAR_ID_CB_CELL_NUM);
	if(cell_num >= CELL_MAX_NUM)
		cell_num = CELL_MAX_NUM; 
	
	tx_buf[tx_idx ++ ] = cell_num;
	for(i = 0;i < cell_num; ++ i)
	{
		data_val = var_get_data(VAR_ID_CELL_VOLT01 + i);
		tx_buf[tx_idx ++ ] = data_val >> 8;
		tx_buf[tx_idx ++ ] = data_val & 0xff;
	}
	
	data_val = 0;
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = 0;
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	data_val = heat_cnt ++;
	tx_buf[tx_idx ++ ] = data_val >> 8;
	tx_buf[tx_idx ++ ] = data_val & 0xff;
	
	tx_buf[tx_idx ++ ] = 0;
	
	tx_buf[4] = tx_idx - 4;
    calc_crc = pc_jb_calc_crc(&tx_buf[1] , tx_idx - 1);
    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}	

static uint8_t jbd_write_cmd_E1_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;
	
	if(recv_data.data_buf[0] == 0x00)
	{
		//if(var_get_data(VAR_ID_PARAM_LOCK) == 0x55)
		{
			if(recv_data.data_buf[1] & 0x03)
				var_set_data(VAR_ID_MOS_LOCK , recv_data.data_buf[1] | 0xAA00);
			else
				var_set_data(VAR_ID_MOS_LOCK , 0);
		}
	}
	
    calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_read_cmd_param_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	uint16_t param_val = 0;
	uint16_t i = 0;
	uint8_t err_flag = 0;
	char str[30] = "";
	uint8_t len = 0;
	uint16_t v16_data = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
	tx_buf[tx_idx ++ ] = recv_data.dev_addr;
	//tx_buf[tx_idx ++ ] = recv_data.wr_cmd;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;

	if(recv_data.reg_cmd < 0xa0)
	{
		switch(recv_data.reg_cmd)
		{
			case 0x10:  // 设计容量
				param_val = param_get_data(PAR_ID_STD_CAP);
				break;
			case 0x11:  // 循环容量
				param_val = 0.01 * param_get_data(PAR_ID_CYCLE_COEFF) * param_get_data(PAR_ID_STD_CAP);
				break;
			case 0x12:  // 单体充满电压
				param_val = 3600;
				break;
			case 0x13:  // 单体截止电压
				param_val = 2700;
				break;
			case 0x14:  // 自放电率
				param_val = param_get_data(PAR_ID_BATT_SELF_POW);
				break;
			case 0x15:  // 生产日期
				param_val = (param_get_data(PAR_ID_BMS_YEAR) - 2000) & 0x7F;
				param_val <<= 4;
				param_val += param_get_data(PAR_ID_BMS_MONTH);
				param_val <<= 5;
				param_val += param_get_data(PAR_ID_BMS_DAY);
				break;
			case 0x16:  // 序列号 
				param_val = param_get_data(PAR_ID_PCS_CAN_TYPE);
				break;
			case 0x17:
				param_val = param_get_data(PAR_ID_CYCLE);
				break;
			case 0x18: // 充电高温保护
				param_val = param_get_data(PAR_ID_OTC_PRP_VAL) + 2231;
				break;
			case 0x19:
				param_val = param_get_data(PAR_ID_OTC_PRP_RCV) + 2231;
				break;
			case 0x1A:
				param_val = param_get_data(PAR_ID_UTC_PRP_VAL) + 2231;
				break;
			case 0x1B:
				param_val = param_get_data(PAR_ID_UTC_PRP_RCV) + 2231;
				break;
			case 0x1C: 
				param_val = param_get_data(PAR_ID_OTD_PRP_VAL) + 2231;
				break;
			case 0x1D:
				param_val = param_get_data(PAR_ID_OTD_PRP_RCV) + 2231;
				break;
			case 0x1E:
				param_val = param_get_data(PAR_ID_UTD_PRP_VAL) + 2231;
				break;
			case 0x1F:
				param_val = param_get_data(PAR_ID_UTD_PRP_RCV) + 2231;
				break;
			case 0x20:
				param_val = param_get_data(PAR_ID_BOV_PRP_VAL);
				break;
			case 0x21:
				param_val = param_get_data(PAR_ID_BOV_PRP_RCV);
				break;
			case 0x22:
				param_val = param_get_data(PAR_ID_BUV_PRP_VAL);
				break;
			case 0x23:
				param_val = param_get_data(PAR_ID_BUV_PRP_RCV);
				break;
			case 0x24:
				param_val = param_get_data(PAR_ID_COV_PRP_VAL);
				break;
			case 0x25:
				param_val = param_get_data(PAR_ID_COV_PRP_RCV);
				break;
			case 0x26:
				param_val = param_get_data(PAR_ID_CUV_PRP_VAL);
				break;
			case 0x27:
				param_val = param_get_data(PAR_ID_CUV_PRP_RCV);
				break;
			case 0x28:
				param_val = param_get_data(PAR_ID_OCC_PRP_VAL) * 10;
				break;
			case 0x29:
				param_val = 0x10000 - param_get_data(PAR_ID_OCD1_PRP_VAL) * 10;
				break;
			case 0x2A:
				param_val = param_get_data(PAR_ID_BLC_VOLT);
				break;
			case 0x2B:
				param_val = param_get_data(PAR_ID_BLC_VDIFF);
				break;
			case 0x2C:
				param_val = CURR_SMP_RES * 10;
				break;
			case 0x2D:
				param_val = 0; //功能配置
				break;
			case 0x2E:
				param_val = 0;  //温度探头配置
				break;
			case 0x2F:
				param_val =  param_get_data(PAR_ID_CB_CELL_NUM);
				break;
			case 0x30:
				param_val = 0; //开关控制时间
				break;
			case 0x31:
				param_val = 0; //LED工作时间
				break;
			case 0x32:
				param_val = 3329;
				break;
			case 0x33:
				param_val = 3322;
				break;
			case 0x34:
				param_val = 3280;
				break;
			case 0x35:
				param_val =	3219;
				break;
			case 0x36:
				param_val = 3750;
				break;
			case 0x37:
				param_val = 2500;
				break;
			case 0x38:
				param_val = 0xE2;//param_get_data(PAR_ID_OCC_PRP_VAL) * 10+100;  //二级过流保护设置
				break;
			case 0x39:
				param_val = 0xf7;  //短路保护设置43
				break;
			case 0x3A:
				param_val = ((param_get_data(PAR_ID_UTC_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_OTC_PRP_DLY)/1000;
				break;
			case 0x3B:
				param_val = ((param_get_data(PAR_ID_UTD_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_OTD_PRP_DLY)/1000;
				break;
			case 0x3C:
				param_val = ((param_get_data(PAR_ID_BUV_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_BOV_PRP_DLY)/1000;
				break;
			case 0x3D:
				param_val = ((param_get_data(PAR_ID_CUV_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_COV_PRP_DLY)/1000;
				break;
			case 0x3E:
				param_val = ((param_get_data(PAR_ID_OCC_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_OCC_RCV_DLY);
				break;
			case 0x3F:
				param_val = ((param_get_data(PAR_ID_OCD1_PRP_DLY) /1000) << 8) + param_get_data(PAR_ID_OCD1_RCV_DLY);
				break;
			case 0x40:
				param_val = 0;//生产厂商？
				break;
			case 0x41:
				param_val = 0;
				break;
			case 0x42:
				param_val = 3330;
				break;
			case 0x43:
				param_val = 3325;
				break;
			case 0x44:
				param_val = 3301;
				break;
			case 0x45:
				param_val = 3280;
				break;
			case 0x46:
				param_val = 3220;
				break;
			case 0x47:
				param_val = 3350;
				break;
			case 0x48:
				break;
			case 0x49:
				break;
			case 0x4A:
				break;
			case 0x4B:
				break;
			case 0x4C:
				break;
			case 0x4D:
				break;
			case 0x4E:
				break;
			case 0x4F:
				break;
			case 0x50:
				break;
			case 0x51:
				break;
			default:
				err_flag = 1;
				break;
		}
	    tx_buf[tx_idx ++ ] = 0x00;
		tx_buf[tx_idx ++ ] = 0x02;
		
		tx_buf[tx_idx ++ ] = param_val >> 8;
		tx_buf[tx_idx ++ ] = param_val & 0xff;
	}
	else
	{
	 if (recv_data.dev_addr == BROAD_ADDR)
	 {	 
		switch(recv_data.reg_cmd)
			{
			case 0xa0:
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = 0x1F;
				tx_buf[tx_idx ++ ] = 0x1E;
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_SN_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[3] = len + 1;
				tx_buf[4] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			case 0xa1:
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = 0x1F;
				tx_buf[tx_idx ++ ] = 0x1E;
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_BMS_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[3] = len + 1;
				tx_buf[4] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			case 0xa2:
				//DD 00 A2 00
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = 0x1F;
				tx_buf[tx_idx ++ ] = 0x1E;
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_MFT_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[3] = len + 1;
				tx_buf[4] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			default:
				err_flag = 1;
		 		break;
		    }
		}
	 else
	 {	 
		switch(recv_data.reg_cmd)
			{
			case 0xa0:
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = tx_buf[4];
				tx_buf[tx_idx ++ ] = tx_buf[5];
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_SN_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[4] = len + 1;
				tx_buf[5] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			case 0xa1:
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = tx_buf[4];
				tx_buf[tx_idx ++ ] = tx_buf[5];
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_BMS_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[3] = len + 1;
				tx_buf[4] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			case 0xa2:
				//DD 00 A2 00
				tx_buf[tx_idx ++ ] = 0x00;
				tx_buf[tx_idx ++ ] = tx_buf[4];
				tx_buf[tx_idx ++ ] = tx_buf[5];
				for(i = 0;i < 15; ++ i)
				{
					v16_data = param_get_data(PAR_ID_MFT_CODE + i);
					str[i * 2] = v16_data;
					str[i * 2 + 1] = v16_data >> 8;
				}
				
				len = strlen(str);
				tx_buf[4] = len + 1;
				tx_buf[5] = len;
				for(i = 0;i < len; ++ i)
				{
					tx_buf[tx_idx ++] = str[i];
				}
				break;
			default:
				err_flag = 1;
				break;
			}
		}	 
	}

    calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    if(0 == err_flag)
		return TRUE;
	else
		return FALSE;
}

static uint8_t jbd_write_cmd_param_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num) //OK
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	uint16_t param_val = 0;
	uint16_t i = 0;
	uint8_t err_flag = 0;
	char str[30] = "";
	uint16_t set_val = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
	//tx_buf[tx_idx ++ ] = recv_data.wr_cmd;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
	tx_buf[tx_idx ++ ] = 0;
	tx_buf[tx_idx ++ ] = 0;
	
	if(recv_data.reg_cmd < 0xa0)
	{
		param_val = (recv_data.data_buf[0] << 8) + recv_data.data_buf[1];
		switch(recv_data.reg_cmd)
		{
			case 0x10:  // 设计容量
				param_set_data(PAR_ID_STD_CAP  , param_val);
				param_set_data(PAR_ID_FULL_CAP , param_val);
				set_val = var_get_data(VAR_ID_DISP_RCAP) * 10000 / param_get_data(PAR_ID_FULL_CAP);
				soc_calc_set_soc(set_val);
				param_set_data(PAR_ID_SOH      , 100);
				param_set_data(PAR_ID_SOH_ST_CYCLE , param_get_data(PAR_ID_CYCLE));
				break;
			case 0x11:  // 循环容量
				param_val = param_val * 100 / param_get_data(PAR_ID_STD_CAP);
				param_set_data(PAR_ID_CYCLE_COEFF , param_val);
				break;
			case 0x12:  // 单体充满电压
				param_val = 3600;
				break;
			case 0x13:  // 单体截止电压
				param_val = 2700;
				break;
			case 0x14:  // 自放电率
				param_set_data(PAR_ID_BATT_SELF_POW , param_val);
				break;
			case 0x15:  // 生产日期
				param_set_data(PAR_ID_BMS_YEAR , ((param_val >> 9) & 0x7F) + 2000);
				param_set_data(PAR_ID_BMS_MONTH , (param_val >> 5) & 0x0F);
				param_set_data(PAR_ID_BMS_DAY , param_val& 0x1F);
				break;
			case 0x16:  // 序列号 
			    param_set_data(PAR_ID_PCS_CAN_TYPE , param_val);
				break;
			case 0x17:
				soh_set_cycle(param_val);
				break;
			case 0x18: // 充电高温保护
				param_set_data(PAR_ID_OTC_PRP_VAL , param_val - 2231);
				break;
			case 0x19:
			    param_set_data(PAR_ID_OTC_PRP_RCV , param_val - 2231);
				break;
			case 0x1A:
				param_set_data(PAR_ID_UTC_PRP_VAL , param_val - 2231);
				break;
			case 0x1B:
				param_set_data(PAR_ID_UTC_PRP_RCV , param_val - 2231);
				break;
			case 0x1C: 
				param_set_data(PAR_ID_OTD_PRP_VAL , param_val - 2231);
				break;
			case 0x1D:
				param_set_data(PAR_ID_OTD_PRP_RCV , param_val - 2231);
				break;
			case 0x1E:
				param_set_data(PAR_ID_UTD_PRP_VAL , param_val - 2231);
				break;
			case 0x1F:
				param_set_data(PAR_ID_UTD_PRP_RCV , param_val - 2231);
				break;
			case 0x20:
			    param_set_data(PAR_ID_BOV_PRP_VAL , param_val);
				break;
			case 0x21:
				param_set_data(PAR_ID_BOV_PRP_RCV , param_val);
				break;
			case 0x22:
				param_set_data(PAR_ID_BUV_PRP_VAL , param_val);
				break;
			case 0x23:
				param_set_data(PAR_ID_BUV_PRP_RCV , param_val);
				break;
			case 0x24:
				param_set_data(PAR_ID_COV_PRP_VAL , param_val);
				break;
			case 0x25:
				param_set_data(PAR_ID_COV_PRP_RCV , param_val);
				break;
			case 0x26:
				param_set_data(PAR_ID_CUV_PRP_VAL , param_val);
				break;
			case 0x27:
				param_set_data(PAR_ID_CUV_PRP_RCV , param_val);
				break;
			case 0x28:
				param_set_data(PAR_ID_OCC_PRP_VAL , param_val);
				break;
			case 0x29:
				param_set_data(PAR_ID_OCD1_PRP_VAL , (0x10000 - param_val) * 0.1);
				break;
			case 0x2A:
				param_set_data(PAR_ID_BLC_VOLT , param_val);
				break;
			case 0x2B:
				param_set_data(PAR_ID_BLC_VDIFF , param_val);
				break;
			case 0x2C:
				param_val = CURR_SMP_RES * 10;
				break;
			case 0x2D:
				param_val = 0;
				break;
			case 0x2E:
				param_val = 0;
				break;
			case 0x2F:
				param_val = param_get_data(PAR_ID_CB_CELL_NUM);
				break;
			case 0x30:
				param_val = 0;
				break;
			case 0x31:
				param_val = 0;
				break;
			case 0x32:
				param_val = 3329;
				break;
			case 0x33:
				param_val = 3322;
				break;
			case 0x34:
				param_val = 3280;
				break;
			case 0x35:
				param_val = 3219;
				break;
			case 0x36:
				param_val = 3650;
				break;
			case 0x37:
				param_val = 2500;
				break;
			case 0x38:
				param_val = 0;
				break;
			case 0x39:
				param_val = 0;
				break;
			case 0x3A:
				param_set_data(PAR_ID_UTC_PRP_DLY , (param_val >> 8) * 1000);
				param_set_data(PAR_ID_OTC_PRP_DLY , (param_val & 0xff) * 1000);
				break;
			case 0x3B:
				param_set_data(PAR_ID_UTD_PRP_DLY , (param_val >> 8) * 1000);
				param_set_data(PAR_ID_OTD_PRP_DLY , (param_val & 0xff) * 1000);
				break;
			case 0x3C:
				param_set_data(PAR_ID_BUV_PRP_DLY , (param_val >> 8) * 1000);
				param_set_data(PAR_ID_BOV_PRP_DLY , (param_val & 0xff) * 1000);
				break;
			case 0x3D:
				param_set_data(PAR_ID_CUV_PRP_DLY , (param_val >> 8) * 1000);
				param_set_data(PAR_ID_COV_PRP_DLY , (param_val & 0xff) * 1000);
				break;
			case 0x3E:
				param_set_data(PAR_ID_OCC_PRP_DLY , (param_val >> 8) * 1000);
				//param_set_data(PAR_ID_OCC_RCV_DLY , (param_val & 0xff));
				break;
			case 0x3F:
				param_set_data(PAR_ID_OCD1_PRP_DLY , (param_val >> 8) * 1000);
				param_set_data(PAR_ID_OCD1_RCV_DLY , (param_val & 0xff));
				break;
			case 0x40:
				param_val = 0;
				break;
			case 0x41:
				param_val = 0;
				break;
			case 0x42:
				param_val = 3330;
				break;
			case 0x43:
				param_val = 3325;
				break;
			case 0x44:
				param_val = 3301;
				break;
			case 0x45:
				param_val = 3280;
				break;
			case 0x46:
				param_val = 3220;
				break;
			case 0x47:
				param_val = 3350;
				break;
			case 0x48:
				break;
			case 0x49:
				break;
			case 0x4A:
				break;
			case 0x4B:
				break;
			case 0x4C:
				break;
			case 0x4D:
				break;
			case 0x4E:
				break;
			case 0x4F:
				break;
			case 0x50:
				break;
			case 0x51:
				break;
			case 0xa0:
				param_val = 3220;
				break;
			case 0xa1:
				param_val = 3220;
				break;
			case 0xa2:
				param_val = 3220;
				break;
			default:
				err_flag = 1;
				break;
		}
	}
	else
	{
		switch(recv_data.reg_cmd)
		{
			case 0xa0:
				for(i = 0;(i < recv_data.data_buf[0]) && (i < 30) ; i ++)
				{
					str[i] =  recv_data.data_buf[1 + i];
				}
				
				for(i = 0;i < 15 ; i ++)
				{
					param_set_data(PAR_ID_SN_CODE + i , str[i * 2] + (str[i * 2 + 1] << 8));
				}
				break;
			case 0xa1:
				for(i = 0;(i < recv_data.data_buf[0]) && (i < 30) ; i ++)
				{
					str[i] =  recv_data.data_buf[1 + i];
				}
				
				for(i = 0;i < 15 ; i ++)
				{
					param_set_data(PAR_ID_BMS_CODE + i , str[i * 2] + (str[i * 2 + 1] << 8));
				}
				
				break;
			case 0xa2:
				for(i = 0;(i < recv_data.data_buf[0]) && (i < 30) ; i ++)
				{
					str[i] =  recv_data.data_buf[1 + i];
				}
				
				for(i = 0;i < 15 ; i ++)
				{
					param_set_data(PAR_ID_MFT_CODE + i , str[i * 2] + (str[i * 2 + 1] << 8));
				}
				break;
			default:
				err_flag = 1;
				break;
		}
	}

    calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
	if(0 == err_flag)
		return TRUE;
	else
		return FALSE;
}

static uint8_t jbd_write_cmd_unlock_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;
	
	if((0x56 == recv_data.data_buf[0]) || (0x78 == recv_data.data_buf[0]))
		var_set_data(VAR_ID_PARAM_LOCK , 0x55);
	
    calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint8_t jbd_write_cmd_lock_deal(pc_jbd_data_type recv_data, uint8_t *tx_buf, uint16_t *tx_num)
{
	uint16_t tx_idx = 0;
    uint16_t calc_crc = 0;
	
    tx_buf[tx_idx ++ ] = FRAME_HARD;
	if(recv_data.dev_addr != BROAD_ADDR)
		tx_buf[tx_idx ++ ] = recv_data.dev_addr;
    tx_buf[tx_idx ++ ] = recv_data.reg_cmd;
    tx_buf[tx_idx ++ ] = 0x00;
    tx_buf[tx_idx ++ ] = 0x00;
	
	var_set_data(VAR_ID_PARAM_LOCK , 0x00);
	
    calc_crc = pc_jb_calc_crc(&tx_buf[2] , tx_idx - 2);

    tx_buf[tx_idx ++ ] = calc_crc >> 8;
    tx_buf[tx_idx ++ ] = calc_crc & 0xff;

    tx_buf[tx_idx ++ ] = FRAME_END;
	*tx_num = tx_idx;
    return TRUE;
}

static uint16_t jbd_get_prp_state(void)
{
    uint16_t prp_msg = 0;
	if(diag_get_prp(PRP_ID_COV))
		prp_msg |= BIT0;
	if(diag_get_prp(PRP_ID_CUV))
		prp_msg |= BIT1;
	if(diag_get_prp(PRP_ID_BOV))
		prp_msg |= BIT2;
	if(diag_get_prp(PRP_ID_BUV))
		prp_msg |= BIT3;
	if(diag_get_prp(PRP_ID_OTC))
		prp_msg |= BIT4;
	if(diag_get_prp(PRP_ID_UTC))
		prp_msg |= BIT5;
	if(diag_get_prp(PRP_ID_OTD))
		prp_msg |= BIT6;
	if(diag_get_prp(PRP_ID_UTD))
		prp_msg |= BIT7;
	if(diag_get_prp(PRP_ID_OCC) | diag_get_prp(PRP_ID_OCC2))
		prp_msg |= BIT8;
	if(diag_get_prp(PRP_ID_OCD) | diag_get_prp(PRP_ID_OCD2))
		prp_msg |= BIT9;
	if(diag_get_prp(PRP_ID_SC))
		prp_msg |= BIT10;
	if(diag_get_prp(PRP_ID_COL) | diag_get_prp(PRP_ID_FT_AFE) | diag_get_prp(PRP_ID_TOL))
		prp_msg |= BIT11;
	if((var_get_data(VAR_ID_MOS_LOCK) & 0xAA00) == 0xAA00)
		prp_msg |= BIT12;
	if(diag_get_prp(PRP_ID_FT_CMOS))//修改20240125
		prp_msg |= BIT13;
	if(diag_get_prp(PRP_ID_FT_DMOS))
		prp_msg |= BIT14;
	if(diag_get_prp(PRP_ID_OTM)||diag_get_prp(PRP_ID_UTE)||diag_get_prp(PRP_ID_OTE)) //预留
		prp_msg |= BIT15;
	
    return prp_msg;
}

static uint16_t jbd_get_alm_state(void)
{
    uint16_t alm_msg = 0;

	if(diag_get_alarm(ALM_ID_COV))
		alm_msg |= BIT0;
	if(diag_get_alarm(ALM_ID_CUV))
		alm_msg |= BIT1;
	if(diag_get_alarm(ALM_ID_BOV))
		alm_msg |= BIT2;
	if(diag_get_alarm(ALM_ID_BUV))
		alm_msg |= BIT3;
	if(diag_get_alarm(ALM_ID_OTC))
		alm_msg |= BIT4;
	if(diag_get_alarm(ALM_ID_UTC))
		alm_msg |= BIT5;
	if(diag_get_alarm(ALM_ID_OTD))
		alm_msg |= BIT6;
	if(diag_get_alarm(ALM_ID_UTD))
		alm_msg |= BIT7;
	if(diag_get_alarm(ALM_ID_OCC))
		alm_msg |= BIT8;
	if(diag_get_alarm(ALM_ID_OCD))
		alm_msg |= BIT9;
	if(diag_get_alarm(ALM_ID_TDIFF))
		alm_msg |= BIT10;
	if(diag_get_alarm(ALM_ID_SOCL))
		alm_msg |= BIT11;
	if(diag_get_alarm(ALM_ID_OTM))
		alm_msg |= BIT12;
	if(diag_get_alarm(ALM_ID_OTE))
		alm_msg |= BIT13;
	if(diag_get_alarm(ALM_ID_UTE))
		alm_msg |= BIT14;
   
    return alm_msg;
}

static uint16_t jbd_get_pcs_rs485_ptl(void)
{
	uint16_t res_val = 0;
	uint16_t par_val = 0;
	
	par_val = param_get_data(PAR_ID_PCS_RS485_TYPE);
	
	if(par_val == PCS_RS485_PYLON)
		res_val = 1;
	else if(par_val == PCS_RS485_GROWATT)
		res_val = 2;
	else if(par_val == PCS_RS485_VOLTRONIC)
		res_val = 3;
	else if(par_val == PCS_RS485_LXP)
		res_val = 4;
	else if(par_val == PCS_RS485_DEYE)
		res_val = 5;
	else if(par_val == PCS_RS485_INVT)
		res_val = 6;
	else if(par_val == PCS_RS485_SRNE)
		res_val = 7;
	else if(par_val == PCS_RS485_HNJD)
		res_val = 8;
	else if(par_val == PCS_RS485_IY)
		res_val = 9;
	else if(par_val == PCS_RS485_VMII)
		res_val = 10;
	else if(par_val == PCS_RS485_SAKO)
		res_val = 11;
	else if(par_val == PCS_RS485_GOGHAMP)
		res_val = 12;
	else if(par_val == PCS_RS485_SMK)
		res_val = 13;
	else if(par_val == PCS_RS485_PACE)
		res_val = 14;
	else if(par_val == PCS_RS485_EXP8)
		res_val = 15;
	else if(par_val == PCS_RS485_EXP9)
		res_val = 16;
	else 
		res_val = par_val + 1;
	
	if(res_val > 16)
		res_val = 1;
	
	return res_val;
}

static uint16_t jbd_get_pcs_can_ptl(void)
{
	uint16_t res_val = 1;
	uint16_t par_val = 1;
	
	par_val = param_get_data(PAR_ID_PCS_CAN_TYPE);
	
	if(par_val == PCS_CAN_PYLON)
		res_val = 1;
	else if(par_val == PCS_CAN_VICTRON)
		res_val = 2;
	else if(par_val == PCS_CAN_GOODWE)
		res_val = 3;
	else if(par_val == PCS_CAN_GROWATT)
		res_val = 4;
	else if(par_val == PCS_CAN_LXP)
		res_val = 5;
	else if(par_val == PCS_CAN_DEYE)
		res_val = 6;
	else if(par_val == PCS_CAN_SOFAR)
		res_val = 7;
	else if(par_val == PCS_CAN_GINLONG)
		res_val = 8;
	else if(par_val == PCS_CAN_SMA)
		res_val = 9;
	else if(par_val == PCS_CAN_MUST)
		res_val = 10;
	else if(par_val == PCS_CAN_VMII)
		res_val = 11;
	else if(par_val == PCS_CAN_SRNE)
		res_val = 12;
	else if(par_val == PCS_CAN_INVENT)
		res_val = 13;
	else if(par_val == PCS_CAN_SOROUPS)
		res_val = 14;
	else if(par_val == PCS_CAN_AISWEI)
		res_val = 15;
	else if(par_val == PCS_CAN_KSTAR)
		res_val = 16;
	else
		res_val = 1;
	
	if(res_val == 0)
		res_val = 1;

	return res_val;
}

static void jbd_set_pcs_rs485_ptl(uint16_t set_dat)
{
	uint8_t par_val = 0xFF;

	if(set_dat == 1)
		par_val = PCS_RS485_PYLON;
	else if(set_dat == 2)
		par_val = PCS_RS485_GROWATT;
	else if(set_dat == 3)
		par_val = PCS_RS485_VOLTRONIC;
	else if(set_dat == 4)
		par_val = PCS_RS485_LXP;
	else if(set_dat == 5)
		par_val = PCS_RS485_DEYE;
	else if(set_dat == 6)
		par_val = PCS_RS485_INVT;
	else if(set_dat == 7)
		par_val = PCS_RS485_SRNE;
	else if(set_dat == 8)
		par_val = PCS_RS485_HNJD;
	else if(set_dat == 9)
		par_val = PCS_RS485_IY;
	else if(set_dat == 10)
		par_val = PCS_RS485_VMII;
	else if(set_dat == 11)
		par_val = PCS_RS485_SAKO;
	else if(set_dat == 12)
		par_val = PCS_RS485_GOGHAMP;
	else if(set_dat == 13)
		par_val = PCS_RS485_SMK;
	else if(set_dat == 14)
		par_val = PCS_RS485_PACE;
	else if(set_dat == 15)
		par_val = PCS_RS485_EXP8;
	else if(set_dat == 16)
		par_val = PCS_RS485_EXP9;
	else
		par_val = 0;
	
	if(par_val != 0xFF)
	{
		If_com_init_drv(COM_PCS , 9600);

		param_set_data(PAR_ID_PCS_RS485_TYPE , par_val);
	}
}

static void jbd_set_pcs_can_ptl(uint16_t set_dat)
{
	uint8_t par_val = 0xFF;
	
	if(1 == set_dat)
		par_val = PCS_CAN_PYLON;
	else if(set_dat == 2)
		par_val = PCS_CAN_VICTRON;
	else if(set_dat == 3)
		par_val = PCS_CAN_GOODWE;
	else if(set_dat == 4)
		par_val = PCS_CAN_GROWATT;
	else if(set_dat == 5)
		par_val = PCS_CAN_LXP;
	else if(set_dat == 6)
		par_val = PCS_CAN_DEYE;
	else if(set_dat == 7)
		par_val = PCS_CAN_SOFAR;
	else if(set_dat == 8)
		par_val = PCS_CAN_GINLONG;
	else if(set_dat == 9)
		par_val = PCS_CAN_SMA;
	else if(set_dat == 10)
		par_val = PCS_CAN_MUST;
	else if(set_dat == 11)
		par_val = PCS_CAN_VMII;
	else if(set_dat == 12)
		par_val = PCS_CAN_SRNE;
	else if(set_dat == 13)
		par_val = PCS_CAN_INVENT;
	else if(set_dat == 14)
		par_val = PCS_CAN_SOROUPS;
	else if(set_dat == 15)
		par_val = PCS_CAN_AISWEI;
	else if(set_dat == 16)
		par_val = PCS_CAN_KSTAR;
	else
	{
		par_val = 0xff;
	}
	
	if(par_val != 0xFF)
	{
		if(par_val != PCS_CAN_MUST)
		{
			If_can_init(CAN_ID1 , 500000);
		}
		else
		{
			If_can_init(CAN_ID1 , 100000);
		}
		
		param_set_data(PAR_ID_PCS_CAN_TYPE , par_val);
	}
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/


